home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 …ember: Reference Library / Dev.CD Dec 97 RL.toast / What's New / Tool Chest / Testing & Debugging / Virtual User / Examples / External Tool Templates / CPlus Tool Template / RequestDispatcher.cp < prev    next >
Encoding:
Text File  |  1997-10-15  |  23.7 KB  |  895 lines  |  [TEXT/MPS ]

  1. /*
  2.  *    File:        RequestDispatcher.cp
  3.  *
  4.  *    Contains:    xxx put contents here xxx
  5.  *
  6.  *    Written by:    Rick Violet
  7.  *
  8.  *    Copyright:    © 1992 by Apple Computer, Inc., all rights reserved.
  9.  *
  10.  *    Change History (most recent first):
  11.  *
  12.  *        <1+>     8/30/93    RV        Add ReadVersion service
  13.  *         <6>      7/8/93    RV        Fix DoGetToolServices not to drop last service name
  14.  *        <5+>      7/8/93    RV        Fix DoGetToolServices not to drop last service name
  15.  *         <2>     4/15/93    RV        Fix Memory Leak in DispatchCustomRequest
  16.  *        <1+>     4/15/93    RV        Fix Memory Leak in DispatchCustomRequest
  17.  *                11/18/92    RV        xxx put comment here xxx
  18.  *
  19.  *    To Do:
  20.  */
  21.  
  22. #ifdef    THINK_CPLUS
  23.     #ifndef        __Strings__
  24.     #include        <String.h>
  25.     #endif
  26. #else
  27.     #include     <Strings.h>
  28. #endif
  29.  
  30. #ifndef        __MEMORY__
  31. #include        <Memory.h>
  32. #endif
  33.  
  34. #ifndef        __RESOURCES__
  35. #include        <Resources.h>
  36. #endif
  37.  
  38. #ifndef        __GESTALTEQU__
  39. #include        <GestaltEqu.h>
  40. #endif
  41.  
  42. #ifndef        __Application__
  43. #include        "Application.h"
  44. #endif
  45.  
  46. #ifndef        __RequestDispatcher__
  47. #include        "RequestDispatcher.h"
  48. #endif
  49.  
  50. #ifdef        __AERequest__
  51. #include        "AERequest.h"
  52. #endif
  53.  
  54. #ifndef        __StandardServices__
  55. #include        "StandardServices.h"
  56. #endif
  57.  
  58. //—————————————————————————————————————————————————————————————————————————————————————
  59. //                                Global Variables
  60. //—————————————————————————————————————————————————————————————————————————————————————
  61.         RequestDispatcher*        gTheRequestDispatcher;
  62. extern    Application*            gTheApplication;
  63.  
  64. extern    ThreadID                gRequestDispatcherThreadID;
  65.  
  66.  
  67. //—————————————————————————————————————————————————————————————————————————————————————
  68. //                                External Routines
  69. //—————————————————————————————————————————————————————————————————————————————————————
  70. extern    void    TerminalError(short errResID, short errCode);    
  71.  
  72. //—————————————————————————————————————————————————————————————————————————————————————
  73. //    RequestDispatcher::RequestDispatcher    -    constructor.
  74. //—————————————————————————————————————————————————————————————————————————————————————
  75. RequestDispatcher::RequestDispatcher()
  76. {
  77.     fRequestQueue = nil;
  78.     fServices = nil;
  79.  
  80.         //————    Construct a Queue for incoming requests
  81.     fRequestQueue = new List();
  82.     if( fRequestQueue == nil )
  83.     {
  84.         TerminalError( kDispatcherErrStrings, kReqQueueConstructErr );
  85.     }
  86.         
  87.         //————    Construct a Queue for Services
  88.     fServices = new List();
  89.     if( fServices == nil )
  90.     {
  91.         TerminalError( kDispatcherErrStrings, kServQueueConstructErr );
  92.     }
  93.     
  94.         /*SBR Hacked this in 10/16/94 */
  95.         //————    Construct a List for currently active Requests
  96.     fActiveRequestList = new List();
  97.     if( fActiveRequestList == nil )
  98.     {
  99.         TerminalError( kDispatcherErrStrings, kServQueueConstructErr );
  100.     }
  101.     
  102.         //————    Install all the Request Handlers
  103.     ConstructAllServiceObjects();
  104.     ConstructServicesMenu();
  105. }
  106.  
  107. //—————————————————————————————————————————————————————————————————————————————————————
  108. //    RequestDispatcher::~RequestDispatcher    -    destructor.
  109. //—————————————————————————————————————————————————————————————————————————————————————
  110. RequestDispatcher::~RequestDispatcher()
  111. {
  112.         //————    Delete all the Queued Requests
  113.     if( fRequestQueue )
  114.     {
  115.         fRequestQueue->DisposeAll();
  116.         delete fRequestQueue;
  117.     }
  118.         
  119.         /*SBR Hacked this in 10/16/94 */
  120.         //————    Delete all the Active Requests
  121.     if( fActiveRequestList )
  122.     {
  123.         fActiveRequestList->DisposeAll();
  124.         delete fActiveRequestList;
  125.     }
  126.         
  127.         //————    Delete all the Service Objects
  128.     if( fServices )
  129.     {
  130.         fServices->DisposeAll();
  131.         delete fServices;
  132.     }
  133.     
  134. }
  135.  
  136. //—————————————————————————————————————————————————————————————————————————————————————
  137. //    RequestDispatcher::ConstructAllServices    -    Install all the Service objects.
  138. //
  139. //        This method calls the constructor for each Request handler
  140. //        and installs a pointer to it in the Queue of Services
  141. //
  142. //        You must construct and install your Custom Request Handlers here 
  143. //—————————————————————————————————————————————————————————————————————————————————————
  144. void
  145. RequestDispatcher::ConstructAllServiceObjects()
  146. {
  147.     Service*    tService;
  148.     
  149.         //————    if the List for containing the services does not exist,
  150.         //————    bail out so we don't crash.
  151.     if( fServices == nil )
  152.     {
  153.         return;
  154.     }
  155.     
  156.         //————    Construct the threaded service object : EchoThreadService
  157.     tService =  new EchoThreadService();
  158.     if( tService )
  159.     {
  160.         fServices->AddAsLast( tService );
  161.     }
  162.     
  163.         //————    Construct the non-threaded service object : EchoNoThreadService
  164.     tService =  new EchoNoThreadService();
  165.     if( tService )
  166.     {
  167.         fServices->AddAsLast( tService );
  168.     }
  169.  
  170.         //————    Construct the non-threaded service object : SetSleepTicksService
  171.     tService =  new SetSleepTicksService();
  172.     if( tService )
  173.     {
  174.         fServices->AddAsLast( tService );
  175.     }
  176.  
  177. }
  178.  
  179. /*SBR Hacked this in 05/23/94 from VUAid 2.0b2 by Jon Marsh*/
  180. //—————————————————————————————————————————————————————————————————————————————————————
  181. //    RequestDispatcher::ConstructServicesMenu    -    Create a menu listing installed services.
  182. //—————————————————————————————————————————————————————————————————————————————————————
  183. void
  184. RequestDispatcher::ConstructServicesMenu()
  185. {
  186.     Loop*            tLoop;
  187.     Service*        tService;
  188.     ScriptValue*    tServiceName;
  189.     MenuHandle        servicesMenu;
  190.     char            serviceNameText[256];
  191.     
  192.     servicesMenu = GetMenu(kServicesMenuID);
  193.     tLoop = new Loop( fServices );
  194.     if( tLoop )
  195.     {
  196.         while ( tService = (Service*)(tLoop->GetNext()) ) 
  197.         {
  198.             tServiceName = tService->GetServiceNameText();
  199.             if( tServiceName ) 
  200.             {
  201.                 strcpy (serviceNameText, ((VUString *) tServiceName)->GetText());
  202.                 C2PStr(serviceNameText);
  203.                 AppendMenu(servicesMenu, (ConstStr255Param) serviceNameText);
  204.             }
  205.         }
  206.         delete tLoop;
  207.     }
  208.  
  209. }
  210.  
  211.     /*SBR Hacked this in 10/16/94 */
  212. //—————————————————————————————————————————————————————————————————————————————————————
  213. //    RequestDispatcher::DoRequests    - Process pending Requests in the queue.
  214. //—————————————————————————————————————————————————————————————————————————————————————
  215. void
  216. RequestDispatcher::DoRequests()
  217. {
  218.     OSErr        tErr = noErr;
  219.     Request*    tReq;
  220.     
  221.     // loop and handle requests as they appear in the pending request queue
  222.     while (true)
  223.     {
  224.             //————    Reset any Apple event timeout counters which need it
  225.             //————    Don't allow selfish services to cause others to time out 
  226.         ResetAllTimeOutCounters();
  227.         
  228.             //————    Is there an element in the pending Request Queue?
  229.         if( ( fRequestQueue != nil ) && ( fRequestQueue->Count() > 0 ) )
  230.         {
  231.                 //————    Extract the "oldest" Request from the Queue
  232.                 //————    New ones are added to the end by the application object
  233.             tReq = (Request*)fRequestQueue->GetFirst();
  234.     
  235.                 //————    if we got a Request object
  236.             if( tReq )
  237.             {
  238.                     //————    remove the request from the pending request queue
  239.                 fRequestQueue->Remove( tReq );
  240.             
  241.                     //————    put the request into the active request list
  242.                 fActiveRequestList->AddAsLast( tReq );
  243.                     
  244.                     //————    If request was canceled, do not process it.
  245.                 if( tReq->HasBeenCanceled() )
  246.                 {
  247.                     RequestIsDone( tReq );
  248.                 }
  249.                 else
  250.                 {
  251.                     ProcessRequest( tReq );
  252.                     
  253.                         //————    When ProcessRequest returns, the request is either
  254.                         //————    canceled or done (not threaded), or ready in a new 
  255.                         //————    thread. If canceled or done, complete the request. 
  256.                         //————    If the request is a new thread, yield to it.
  257.                     if( tReq->IsThreaded() && gTheApplication->IsThreaded() )
  258.                     {
  259.                             //————    yield to the thread just created 
  260.                         YieldToThread( tReq->GetThreadID() );
  261.                     }
  262.                     else
  263.                     {
  264.                         RequestIsDone( tReq );
  265.                     }
  266.                 }
  267.  
  268.             }
  269.         }
  270.         else if( gTheApplication->IsThreaded() )
  271.         {
  272.                 //————    App is threaded and no new requests means give up time.
  273.                 //————    This *must* be a yield to any, not a specific yield, 
  274.                 //————    to give time to active threads.
  275.             YieldToAnyThread();
  276.         }
  277.         else
  278.         {
  279.                 //————    no requests and not threaded means just return
  280.             return;
  281.         }
  282.     }
  283. }
  284.  
  285.  
  286.     /*SBR Hacked this in 10/16/94 */
  287. //—————————————————————————————————————————————————————————————————————————————————————
  288. //    RequestDispatcher::RequestIsDone    -    completion routine for ProcessRequest thread
  289. //—————————————————————————————————————————————————————————————————————————————————————
  290. void
  291. RequestDispatcher::RequestIsDone( Request*    pReq )
  292. {
  293.         //————    send the result back to the caller 
  294.     pReq->SendResult();
  295.  
  296.         //————    request is no longer active 
  297.     fActiveRequestList->Remove( pReq );
  298.  
  299.         //————    Reset the cursor, so beach ball is not left there
  300.     InitCursor();
  301.  
  302.     delete pReq;
  303.     
  304. }
  305.  
  306. //—————————————————————————————————————————————————————————————————————————————————————
  307. //    RequestDispatcher::QueueRequest    -    Puts a Request into our Queue
  308. //—————————————————————————————————————————————————————————————————————————————————————
  309. void
  310. RequestDispatcher::QueueRequest( Request* pReq )
  311. {
  312.         //————    if this is a request to cancel a service request,
  313.         //————    then find the service request and cancel it
  314.     if( pReq->IsACancelRequest() )
  315.     {
  316.         DoCancelReq( pReq );
  317.         delete pReq;
  318.     }
  319.     else
  320.     {
  321.             //————    This is not a request to cancel a service request
  322.             //————    so queue it up, for processing later
  323.         if( fRequestQueue != nil )
  324.         {
  325.             fRequestQueue->AddAsLast( pReq );
  326.         }
  327.     }
  328. }
  329.  
  330.         /*SBR Hacked this in 10/16/94 */
  331. //—————————————————————————————————————————————————————————————————————————————————————
  332. //    RequestDispatcher::CancelAllRequests    - Cancel processing of all requests
  333. //—————————————————————————————————————————————————————————————————————————————————————
  334. Boolean
  335. RequestDispatcher::CancelAllRequests()
  336. {
  337.     Loop*            tLoop;
  338.     Request*        tReq;
  339.  
  340.         //————    Cancel all pending Requests
  341.     tLoop = new Loop( fRequestQueue );
  342.     if( tLoop )
  343.     {
  344.         tReq = (Request*)(tLoop->GetNext());
  345.         while( tReq )
  346.         {
  347.             tReq->CancelThisRequest();
  348.             tReq = (Request*)(tLoop->GetNext());
  349.         }
  350.         delete tLoop;
  351.     }
  352.     
  353.         //————    Cancel all active Requests
  354.     tLoop = new Loop( fActiveRequestList );
  355.     if( tLoop )
  356.     {
  357.         tReq = (Request*)(tLoop->GetNext());
  358.         while( tReq )
  359.         {
  360.             tReq->CancelThisRequest();
  361.             tReq = (Request*)(tLoop->GetNext());
  362.         }
  363.         delete tLoop;
  364.     }
  365.  
  366.         //————    Any Requests left in the Pending Request Queue?
  367.     if( ( fRequestQueue != nil ) && ( fRequestQueue->Count() > 0 ) )
  368.     {
  369.         return false;
  370.     }
  371.  
  372.         //————    Any Requests left in the Active Request List?
  373.     if( ( fActiveRequestList != nil ) && ( fActiveRequestList->Count() > 0 ) )
  374.     {
  375.         return false;
  376.     }
  377.     
  378.         //————    No more Requests anywhere, cancelling is complete
  379.     return true;
  380. }
  381.  
  382. //—————————————————————————————————————————————————————————————————————————————————————
  383. //    RequestDispatcher::ProcessRequest    -    Process the Request
  384. //—————————————————————————————————————————————————————————————————————————————————————
  385. void
  386. RequestDispatcher::ProcessRequest( Request* pReq )
  387. {
  388.     char*    tServiceName;
  389.  
  390.         //————    Get the Text of the Service requested
  391.     tServiceName = pReq->GetWhichService();
  392.  
  393.         //————    Check for ServiceSupported request
  394.     if( relstring( tServiceName, (char*)kVUAEHasService, false, true ) == 0 )
  395.     {
  396.         DoServiceSupportedReq( pReq );
  397.         return;
  398.     }
  399.     
  400.         //————    Check for GetToolVersion request
  401.     if( relstring( tServiceName, (char*)kVUAEGetToolVersion, false, true ) == 0 )
  402.     {
  403.         DoGetToolVersReq( pReq );
  404.         return;
  405.     }
  406.  
  407.         //————    Check for GetToolServices request
  408.     if( relstring( tServiceName, (char*)kVUAEGetServiceList, false, true ) == 0 )
  409.     {
  410.         DoGetToolServicesReq( pReq );
  411.         return;
  412.     }
  413.  
  414.         //————    Check for Initialize request
  415.     if( relstring( tServiceName,(char*)kVUAEInitialize, false, true ) == 0 )
  416.     {
  417.         DoInitializeReq( pReq );
  418.         return;
  419.     }
  420.     
  421.         //————    Check for Quit request
  422.     if( relstring( tServiceName,(char*)kVUAEQuitService, false, true ) == 0 )
  423.     {
  424.         gTheApplication->DoMenuCommand( kFileMenuID, kQuitItem );
  425.         return;
  426.     }
  427.     
  428.     DispatchCustomRequest( pReq );
  429.  
  430.     return;
  431.  
  432. }
  433.  
  434. //—————————————————————————————————————————————————————————————————————————————————————
  435. //    RequestDispatcher::DoCancelReq    -    do the cancel Request
  436. //—————————————————————————————————————————————————————————————————————————————————————
  437. void
  438. RequestDispatcher::DoCancelReq( Request* pReq )
  439. {
  440.     Loop*            tLoop;
  441.     Request*        tReq;
  442.     
  443.         /*SBR Hacked this in 10/16/94 */
  444.         //————    First check the Active Request List for the Request to cancel.
  445.     tLoop = new Loop( fActiveRequestList );
  446.     if( tLoop )
  447.     {
  448.         tReq = (Request*)(tLoop->GetNext());
  449.         while( tReq )
  450.         {
  451.                 //————    Is this the Service Object to be canceled?
  452.             if( tReq->IsCancelRequestForThisRequest( pReq ) )
  453.             {
  454.                 tReq->CancelThisRequest();
  455.                 delete tLoop;
  456.                 return;
  457.             }
  458.             tReq = (Request*)(tLoop->GetNext());
  459.         }
  460.         delete tLoop;
  461.     }
  462.  
  463.  
  464.         //————    Now check the Pending Request Queue for the Request to cancel.
  465.     tLoop = new Loop( fRequestQueue );
  466.     if( tLoop )
  467.     {
  468.         tReq = (Request*)(tLoop->GetNext());
  469.         while( tReq )
  470.         {
  471.                 //————    Is this the Service Object to be canceled?
  472.             if( tReq->IsCancelRequestForThisRequest( pReq ) )
  473.             {
  474.                 tReq->CancelThisRequest();
  475.                 delete tLoop;
  476.                 return;
  477.             }
  478.             tReq = (Request*)(tLoop->GetNext());
  479.         }
  480.         delete tLoop;
  481.     }
  482.  
  483.         //————    If the Request was not found, then it was either never received,
  484.         //————    or was completed and returned before the cancel request
  485.         //————    arrived. In either case, just return an empty return value.
  486. }
  487.  
  488. //—————————————————————————————————————————————————————————————————————————————————————
  489. //    RequestDispatcher::DoGetToolVersReq    -    return the version information
  490. //—————————————————————————————————————————————————————————————————————————————————————
  491. void
  492. RequestDispatcher::DoGetToolVersReq( Request* pReq )
  493. {
  494.     VUList*            tReturnList;
  495.     char            tText[256];
  496.     
  497.     tReturnList = new VUList();
  498.     if( tReturnList )
  499.     {
  500.             //————    Get the Tool's Name
  501.         GetToolName( tText );
  502.         tReturnList->PutNthItem( tText );
  503.         
  504.             //————    Get the Tool's Version String
  505.         GetToolVersionString( tText );
  506.         tReturnList->PutNthItem( tText );
  507.  
  508.         pReq->SetReturnValue( tReturnList );
  509.     }
  510.     else
  511.     {
  512.         pReq->SetErrorCode( memFullErr );
  513.         pReq->SetErrorMessage( "Out of memory?" );
  514.     }
  515. }
  516.  
  517. //—————————————————————————————————————————————————————————————————————————————————————
  518. //    RequestDispatcher::DoInitializeReq    -    pass initialize message to all services
  519. //—————————————————————————————————————————————————————————————————————————————————————
  520. void
  521. RequestDispatcher::DoInitializeReq( Request* pReq )
  522. {
  523.     Loop*            tLoop;
  524.     Service*        tService;
  525.  
  526.         //————    Scan through the Service objects, 
  527.         //————    and inform it that we have received an initialize message
  528.     tLoop = new Loop( fServices );
  529.     if( tLoop )
  530.     {
  531.         tService = (Service*)(tLoop->GetNext());
  532.         while( tService )
  533.         {
  534.                 //————    Call the initialize method for the service object
  535.             tService->Initialize( pReq );
  536.             tService = (Service*)(tLoop->GetNext());
  537.         }
  538.     }
  539.     delete tLoop;
  540.     
  541.     if( gTheApplication->IsThreaded() )
  542.         pReq->SetReturnValue( "threading enabled" );
  543.     else
  544.         pReq->SetReturnValue( "threading disabled" );
  545. }
  546.  
  547.  
  548. //—————————————————————————————————————————————————————————————————————————————————————
  549. //    RequestDispatcher::DispatchCustomRequest    -    execute a custom Request
  550. //        This version executes non-threaded services in the RequestDispatcher thread,
  551. //        which causes a problem for a quit request during a long non-threaded
  552. //        service. Since the RequestDispatcher thread is looping in the custom code, it 
  553. //        never sees the quit request in the pending request queue. This is desirable
  554. //        to block new custom service requests, but is not ideal for services like Quit. 
  555. //        This behavior is the same as the 2.0 non-threaded model -- to quit the tool in 
  556. //        the middle of a long asynchronous non-threaded service, you have to cancel 
  557. //        the service, then quit. Threaded services do not have this problem.
  558. //—————————————————————————————————————————————————————————————————————————————————————
  559. void
  560. RequestDispatcher::DispatchCustomRequest( Request* pReq )
  561. {
  562.     Loop*        tLoop;
  563.     Service*    tService;
  564.     char*        tServiceName;
  565.     Str255        tErrMessage;
  566.  
  567.         //————    Get the Text of the Service requested
  568.     tServiceName = pReq->GetWhichService();
  569.     
  570.     if( fServices == nil )
  571.     {
  572.             //————    no Service queue object, bail out
  573.         return;
  574.     }
  575.     
  576.     tLoop = new Loop( fServices );
  577.     if( tLoop )
  578.     {
  579.         tService = (Service*)(tLoop->GetNext());
  580.         while( tService )
  581.         {
  582.                 //————    Is this the Service object which can handle this request?
  583.             if( tService->CanDoService( tServiceName ) )
  584.             {
  585.                     //————    This is the correct Service object,
  586.                     //————    tell it to process the Request object.
  587.  
  588.                     //————    Store a pointer to the Service in the Request
  589.                 pReq->SetService( tService );
  590.  
  591.                     //————    Is it a threaded Service?
  592.                 if( tService->IsThreaded() )
  593.                 {
  594.                     if( gTheApplication->IsThreaded() )
  595.                     {
  596.                         CreateNewRequestThread( pReq );
  597.                     }
  598.                     else
  599.                     {
  600.                             //————    This threaded service can not be processed 
  601.                             //————    because Thread Manager is not present
  602.                         pReq->SetErrorCode( errAEThreadsNotPresent );
  603.                         GetIndString( tErrMessage, kDispatcherErrStrings, 
  604.                                         kThreadsNotPresentErr );
  605.                         pReq->SetErrorMessage( p2cstr( tErrMessage ) );
  606.                     }
  607.                         
  608.                 }
  609.                 else 
  610.                 {
  611.                     tService->ProcessRequest( pReq );
  612.                 }
  613.                     
  614.                     //————    Reset the cursor, so beach ball is not left there
  615.                 InitCursor();
  616.                 delete tLoop;
  617.                 return;
  618.             }
  619.             tService = (Service*)(tLoop->GetNext());
  620.         }
  621.         delete tLoop;
  622.     }
  623.         
  624.         //————    The service which handles this request was not found
  625.         //————    Report error and return
  626.     pReq->SetErrorCode( errAEUnknownService );
  627.     pReq->SetErrorMessage( "Service not found" );
  628. }
  629.  
  630.  
  631. //—————————————————————————————————————————————————————————————————————————————————————
  632. //    RequestDispatcher::CreateNewRequestThread    -    ThreadedService::ProcessRequest()
  633. //—————————————————————————————————————————————————————————————————————————————————————
  634. OSErr
  635. RequestDispatcher::CreateNewRequestThread( Request* pReq )
  636. {
  637.         //————    We are going to process a request for a Service.  
  638.         //————    Create the ProcessRequest thread as suspended, 
  639.         //————    so we can add it to the queue before yielding.
  640.     
  641.     ThreadedService*    tService;
  642.     OSErr                tErr;
  643.     ThreadID            tRequestThread;
  644.     
  645.     tService = (ThreadedService*)(pReq->GetService());
  646.  
  647.     tErr = NewThread 
  648.             (     kCooperativeThread, 
  649.                 (ThreadEntryProcPtr)&ServiceProcessRequestThread,
  650.                 pReq,
  651.                 tService->GetStackSize(),
  652.                 tService->GetThreadOptions(),
  653.                 0,
  654.                 &tRequestThread 
  655.             );
  656.     
  657.     if ( tErr )
  658.     {
  659.         DebugStr( "\pError creating ServiceProcessRequestThread thread." );
  660.         return tErr;
  661.     }
  662.     
  663.         //————    make the new request thread
  664.     tErr = SetThreadState( tRequestThread, kReadyThreadState, kNoThreadID );
  665.     if ( tErr )
  666.     {
  667.         DebugStr( "\pError setting SetThreadState of tRequestThread to kReadyThreadState." );
  668.         return tErr;
  669.     }
  670.     
  671.         //————    store the request's ThreadID
  672.     pReq->SetThreadID( tRequestThread );
  673.     
  674.     return noErr;
  675. }
  676.  
  677.  
  678. //—————————————————————————————————————————————————————————————————————————————————————
  679. //    RequestDispatcher::DoGetToolServicesReq    -    return the list of Request names
  680. //—————————————————————————————————————————————————————————————————————————————————————
  681. void
  682. RequestDispatcher::DoGetToolServicesReq( Request* pReq )
  683. {
  684.     Loop*            tLoop;
  685.     VUList*            tReturnList;
  686.     Service*        tService;
  687.     ScriptValue*    tReturnNames;
  688.     ScriptValue*    tVal;
  689.     char*            tText;
  690.     ValueKind        tVKind;
  691.     short            tLastElement;
  692.     short            i;
  693.     
  694.     tReturnList = new VUList();
  695.     
  696.     if( tReturnList )
  697.     {
  698.             //————    Scan through the Service objects, and collect the
  699.             //————    text of the service names which this tool supports
  700.         tLoop = new Loop( fServices );
  701.         if( tLoop )
  702.         {
  703.             tService = (Service*)(tLoop->GetNext());
  704.             while( tService )
  705.             {
  706.                     //————    Get the service's Name text
  707.                     //————    and append it to the list
  708.                 tReturnNames = tService->GetServiceNameText();
  709.                 if( tReturnNames )
  710.                 {
  711.                     switch( tReturnNames->GetValueKind() )
  712.                     {
  713.                         case kVUListKind:
  714.                         {
  715.                             tLastElement = ((VUList*)tReturnNames)->GetCount();
  716.                             for( i = 1; i <= tLastElement; i++ )
  717.                             {
  718.                                 tVKind = kVUStringKind;
  719.                                 ((VUList*)tReturnNames)->GetNthItem( i, tVal, tVKind );
  720.                                 if( tVal )
  721.                                 {
  722.                                     tText = ((VUString*)tVal)->GetText();
  723.                                     tReturnList->PutNthItem( tText );
  724.                                 }
  725.                             }
  726.                         }
  727.                         break;
  728.                         
  729.                         default:
  730.                         {
  731.                             tText = ((VUString*)tReturnNames)->GetText();
  732.                             tReturnList->PutNthItem( tText );
  733.                         }
  734.                         break;
  735.                         
  736.                     }
  737.                     delete tReturnNames;
  738.                 }
  739.                 tService = (Service*)(tLoop->GetNext());
  740.             }
  741.             delete tLoop;
  742.         }
  743.  
  744.             //————    We have tranversed the entire list of service objects
  745.             //————    and collected each service's name into the list
  746.             //————    now return the list to V.U.
  747.         pReq->SetReturnValue( tReturnList );
  748.     }
  749. }
  750.  
  751. //—————————————————————————————————————————————————————————————————————————————————————
  752. //    RequestDispatcher::DoServiceSupportedReq    -    return the list of Request names
  753. //—————————————————————————————————————————————————————————————————————————————————————
  754. void
  755. RequestDispatcher::DoServiceSupportedReq( Request* pReq )
  756. {
  757.     Loop*            tLoop;
  758.     Service*        tService;
  759.     char*            tSrvText;
  760.     OSErr            tErr;
  761.  
  762.     /*SBR Hacked this in 05/23/94 */
  763.     tErr = pReq->ExtractValueFromNthParam( 1, &tSrvText );
  764.     if( tErr )
  765.     {
  766.         return;
  767.     }
  768.  
  769.         //————    Scan through the Service objects, and inquire if any
  770.         //————    supports the indicated service
  771.     tLoop = new Loop( fServices );
  772.     if( tLoop )
  773.     {
  774.         tService = (Service*)(tLoop->GetNext());
  775.         while( tService )
  776.         {
  777.                 //————    Ask service object if it can do this service,
  778.             if( tService->CanDoService( tSrvText ) )
  779.             {
  780.                     //————    We have found a service object which can handle this
  781.                     //————    request type, return true to V.U.
  782.                 pReq->SetReturnValue( true );
  783.                 return;
  784.             }
  785.             tService = (Service*)(tLoop->GetNext());
  786.         }
  787.         delete tLoop;
  788.     }
  789.     
  790.         //————    We have looked through the entire list of service objects
  791.         //————    and have not found one which handles this request type, so
  792.         //————    return false to V.U.
  793.     pReq->SetReturnValue( false );
  794. }
  795.  
  796. //—————————————————————————————————————————————————————————————————————————————————————
  797. //    RequestDispatcher::GetToolName    
  798. //—————————————————————————————————————————————————————————————————————————————————————
  799. void
  800. RequestDispatcher::GetToolName( char* pText )
  801. {
  802.     strcpy( pText, (char*)gTheApplication->fProcessName );
  803.     p2cstr( (StringPtr)pText );
  804. }
  805.  
  806. //—————————————————————————————————————————————————————————————————————————————————————
  807. //    RequestDispatcher::GetToolVersionString    
  808. //—————————————————————————————————————————————————————————————————————————————————————
  809. void
  810. RequestDispatcher::GetToolVersionString( char* pText )
  811. {
  812.     VersResRecHdl    tVers;
  813.     short            tLength;
  814.     short            i;
  815.     char*            s;
  816.     char*            d;
  817.     
  818.     tVers = (VersResRecHdl)Get1Resource( 'vers', 1 );
  819.     if( tVers )
  820.     {
  821.         HLock( (Handle)tVers );
  822.             
  823.             //————    Set s to point at the length byte of the short version string
  824.         s = (*tVers)->versStr;
  825.  
  826.             //————    Advance s to the length byte of the long version string
  827.             //————    which begins just after the short version string
  828.         s += s[0] + 1;
  829.  
  830.             //————    Get the length of the long version string
  831.         tLength = s[0];
  832.  
  833.             //————    Copy the long version string into pText
  834.         d = pText;
  835.         s++;
  836.         for( i = 0; i < tLength; i++ )
  837.         {
  838.             *d++ = *s++;
  839.         }
  840.         *d = 0;        //————    Terminating Null character
  841.         
  842.         HUnlock( (Handle)tVers );
  843.         ReleaseResource( (Handle)tVers );
  844.     }
  845.     else
  846.     {
  847.         strcpy( pText, "Version string not available." );
  848.     }
  849. }
  850.  
  851. //—————————————————————————————————————————————————————————————————————————————————————
  852. //    RequestDispatcher::ResetAllTimeOutCounters    
  853. //—————————————————————————————————————————————————————————————————————————————————————
  854. void
  855. RequestDispatcher::ResetAllTimeOutCounters()
  856. {
  857.     Loop        tLoop( fRequestQueue );
  858.     Loop        tALoop( fActiveRequestList );
  859.     Request*    tReq;
  860.     
  861.      tReq = (Request*)tLoop.GetNext();    
  862.     while( tReq )
  863.     {
  864.         tReq->ResetTimeOutCounter();
  865.          tReq = (Request*)tLoop.GetNext();    
  866.     }
  867.  
  868.     /*SBR Hacked this in 10/16/94 */
  869.      tReq = (Request*)tALoop.GetNext();    
  870.     while( tReq )
  871.     {
  872.             //————    Use the timeout value defined in the custom Service object
  873.         tReq->ResetTimeOutCounter( tReq->GetService()->GetTimeOutInterval() );
  874.          tReq = (Request*)tALoop.GetNext();
  875.     }
  876. }
  877.  
  878.     /*SBR Hacked this in 10/16/94 */
  879. //—————————————————————————————————————————————————————————————————————————————————————
  880. //    ServiceProcessRequestThread    
  881. //—————————————————————————————————————————————————————————————————————————————————————
  882. void*
  883. ServiceProcessRequestThread( Request* pReq )
  884. {
  885.     Service*    tService;
  886.     
  887.     tService = pReq->GetService();
  888.     tService->ProcessRequest( pReq );
  889.  
  890.     gTheRequestDispatcher->RequestIsDone( pReq );
  891.  
  892.     return nil;        //————    thread is disposed when this function returns
  893. }
  894.  
  895.